package com.castile.sdk.nifi.client.api.impl;

import com.castile.sdk.nifi.client.api.NiFiClientService;
import com.castile.sdk.nifi.client.config.NiFiConfig;
import com.castile.sdk.nifi.client.toolkit.CasApiClient;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.api.toolkit.api.*;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;

import javax.net.ssl.SSLContext;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;

/**
 * @author castile
 * @date 2025-05-16 下午9:30
 */
public class DioNiFiClientService implements NiFiClientService {
    static final String NIFI_CONTEXT = "nifi-api";
    static final int DEFAULT_CONNECT_TIMEOUT = 10000;
    static final int DEFAULT_READ_TIMEOUT = 10000;

    private CasApiClient client;

    private DioNiFiClientService(Builder builder) {
        NiFiConfig config = builder.getConfig();
        if (config == null){
            throw new IllegalArgumentException("nifi config can not be null!");
        }
        String baseUrl = config.getBaseUrl();
        if (StringUtils.isBlank(baseUrl)) {
            throw new IllegalArgumentException("Base URL cannot be blank");
        }

        if (baseUrl.endsWith("/")) {
            baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
        }

        if (!baseUrl.endsWith(NIFI_CONTEXT)) {
            baseUrl = baseUrl + "/" + NIFI_CONTEXT;
        }

        client = new CasApiClient();
        client.setBasePath(baseUrl);
        // 设置SSL Context相关参数

        final SSLContext sslContext = config.getSslContext();

        final ClientBuilder clientBuilder = ClientBuilder.newBuilder();
        if (sslContext != null) {
            clientBuilder.sslContext(sslContext);
        }

        if (config.getHostnameVerifier() != null) {
            clientBuilder.hostnameVerifier(config.getHostnameVerifier());
        }
        int connectTimeout = config.getConnectTimeout() == null ? DEFAULT_CONNECT_TIMEOUT : config.getConnectTimeout();
        int readTimeout = config.getReadTimeout() == null ? DEFAULT_READ_TIMEOUT : config.getReadTimeout();
        final ClientConfig jerseyClientConfig = new ClientConfig();
        jerseyClientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout);
        jerseyClientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout);
        clientBuilder.withConfig(jerseyClientConfig);
        Client buildClient = clientBuilder.build();

        client.setHttpClient(buildClient);
    }

    @Override
    public FlowApi getFlowApi() {
        return new FlowApi(client);
    }

    @Override
    public AccessApi getAccessApi() {
        return new AccessApi(client);
    }

    @Override
    public ControllerApi getControllerApi() {
        return new ControllerApi(client);
    }

    @Override
    public ControllerServicesApi getControllerServicesApi() {
        return new ControllerServicesApi(client);
    }

    @Override
    public CountersApi getCountersApi() {
        return new CountersApi(client);
    }

    @Override
    public ParameterContextsApi getParameterContextsApi() {
        return new ParameterContextsApi(client);
    }

    @Override
    public SystemDiagnosticsApi getSystemDiagnosticsApi() {
        return new SystemDiagnosticsApi(client);
    }

    @Override
    public ProcessorsApi getProcessorsApi() {
        return new ProcessorsApi(client);
    }

    @Override
    public ProcessGroupsApi getProcessGroupsApi() {
        return new ProcessGroupsApi(client);
    }

    @Override
    public ResourcesApi getResourcesApi() {
        return new ResourcesApi(client);
    }

    @Override
    public ReportingTasksApi getReportingTasksApi() {
        return new ReportingTasksApi(client);
    }

    /**
     * Builder for creating a JerseyNiFiClient.
     */
    public static class Builder implements NiFiClientService.Builder {

        private NiFiConfig clientConfig;

        @Override
        public DioNiFiClientService.Builder config(final NiFiConfig clientConfig) {
            this.clientConfig = clientConfig;
            return this;
        }
        @Override
        public NiFiConfig getConfig() {
            return clientConfig;
        }

        @Override
        public NiFiClientService build() {
            return new DioNiFiClientService(this);
        }

    }
}


